<!DOCTYPE html>
<html lang="en-US">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>JavaKeeper</title>
    <meta name="generator" content="VuePress 1.5.4">
    <link rel="icon" href="/icon.svg">
    <script>
        var _hmt = _hmt || [];
        (function() {
            var hm = document.createElement("script");
            hm.src = "https://hm.baidu.com/hm.js?a949a9b30eb86ac0159e735ff8670c03";
            var s = document.getElementsByTagName("script")[0];
            s.parentNode.insertBefore(hm, s);
            // 引入谷歌,不需要可删除这段
            var hm1 = document.createElement("script");
            hm1.src = "https://www.googletagmanager.com/gtag/js?id=UA-169923503-1";
            var s1 = document.getElementsByTagName("script")[0]; 
            s1.parentNode.insertBefore(hm1, s1);
        })();
        // 谷歌加载,不需要可删除
        window.dataLayer = window.dataLayer || [];
        function gtag(){dataLayer.push(arguments);}
        gtag('js', new Date());
        gtag('config', 'UA-169923503-1');
    </script>
    <meta name="description" content="">
    <meta name="keywords" content="JavaKeeper,Java,Java开发,算法,blog">
    <link rel="preload" href="/assets/css/0.styles.91f57736.css" as="style"><link rel="preload" href="/assets/js/app.447d4224.js" as="script"><link rel="preload" href="/assets/js/3.9d76740c.js" as="script"><link rel="preload" href="/assets/js/1.c4fd7d2e.js" as="script"><link rel="preload" href="/assets/js/169.41e753a2.js" as="script"><link rel="prefetch" href="/assets/js/10.8cf3be2c.js"><link rel="prefetch" href="/assets/js/100.74f35ab8.js"><link rel="prefetch" href="/assets/js/101.7a062346.js"><link rel="prefetch" href="/assets/js/102.c9485235.js"><link rel="prefetch" href="/assets/js/103.d88a3805.js"><link rel="prefetch" href="/assets/js/104.6e034144.js"><link rel="prefetch" href="/assets/js/105.d22f7450.js"><link rel="prefetch" href="/assets/js/106.a6cb54b0.js"><link rel="prefetch" href="/assets/js/107.7b65e72b.js"><link rel="prefetch" href="/assets/js/108.eb5804bb.js"><link rel="prefetch" href="/assets/js/109.05f775e5.js"><link rel="prefetch" href="/assets/js/11.c54ae13c.js"><link rel="prefetch" href="/assets/js/110.51d3d641.js"><link rel="prefetch" href="/assets/js/111.022b64a7.js"><link rel="prefetch" href="/assets/js/112.da8afd52.js"><link rel="prefetch" href="/assets/js/113.05a17b18.js"><link rel="prefetch" href="/assets/js/114.8960d913.js"><link rel="prefetch" href="/assets/js/115.67919f68.js"><link rel="prefetch" href="/assets/js/116.62b0cd71.js"><link rel="prefetch" href="/assets/js/117.ebac3eff.js"><link rel="prefetch" href="/assets/js/118.ecd629bd.js"><link rel="prefetch" href="/assets/js/119.a09a0897.js"><link rel="prefetch" href="/assets/js/12.60aa3b24.js"><link rel="prefetch" href="/assets/js/120.bf639d3d.js"><link rel="prefetch" href="/assets/js/121.b89d0c8e.js"><link rel="prefetch" href="/assets/js/122.1a75ff83.js"><link rel="prefetch" href="/assets/js/123.d2127132.js"><link rel="prefetch" href="/assets/js/124.2caff9e0.js"><link rel="prefetch" href="/assets/js/125.9b9f966a.js"><link rel="prefetch" href="/assets/js/126.58cdfb3d.js"><link rel="prefetch" href="/assets/js/127.8ef09c53.js"><link rel="prefetch" href="/assets/js/128.efdc2ae4.js"><link rel="prefetch" href="/assets/js/129.e35cbc57.js"><link rel="prefetch" href="/assets/js/13.125c13a0.js"><link rel="prefetch" href="/assets/js/130.f01a55e3.js"><link rel="prefetch" href="/assets/js/131.65205f4a.js"><link rel="prefetch" href="/assets/js/132.f42c5a0a.js"><link rel="prefetch" href="/assets/js/133.9ba468b3.js"><link rel="prefetch" href="/assets/js/134.7b597ba9.js"><link rel="prefetch" href="/assets/js/135.fb828b9a.js"><link rel="prefetch" href="/assets/js/136.3887532f.js"><link rel="prefetch" href="/assets/js/137.549bae01.js"><link rel="prefetch" href="/assets/js/138.db8d423d.js"><link rel="prefetch" href="/assets/js/139.dbaf2267.js"><link rel="prefetch" href="/assets/js/14.bd1d0b0d.js"><link rel="prefetch" href="/assets/js/140.6cb65fdc.js"><link rel="prefetch" href="/assets/js/141.9bd6cc4b.js"><link rel="prefetch" href="/assets/js/142.552db5ed.js"><link rel="prefetch" href="/assets/js/143.2c9f2bf4.js"><link rel="prefetch" href="/assets/js/144.fba98a15.js"><link rel="prefetch" href="/assets/js/145.c42f3a21.js"><link rel="prefetch" href="/assets/js/146.596d4d33.js"><link rel="prefetch" href="/assets/js/147.c48ae5c1.js"><link rel="prefetch" href="/assets/js/148.71064871.js"><link rel="prefetch" href="/assets/js/149.16582d21.js"><link rel="prefetch" href="/assets/js/15.f247873b.js"><link rel="prefetch" href="/assets/js/150.ead09aca.js"><link rel="prefetch" href="/assets/js/151.971fdf4b.js"><link rel="prefetch" href="/assets/js/152.369c9362.js"><link rel="prefetch" href="/assets/js/153.371edd15.js"><link rel="prefetch" href="/assets/js/154.e090b491.js"><link rel="prefetch" href="/assets/js/155.c68bf602.js"><link rel="prefetch" href="/assets/js/156.304aea8d.js"><link rel="prefetch" href="/assets/js/157.83beef7f.js"><link rel="prefetch" href="/assets/js/158.bb1794b0.js"><link rel="prefetch" href="/assets/js/159.2d54e792.js"><link rel="prefetch" href="/assets/js/16.04336c71.js"><link rel="prefetch" href="/assets/js/160.99d56586.js"><link rel="prefetch" href="/assets/js/161.edf660aa.js"><link rel="prefetch" href="/assets/js/162.0b84606e.js"><link rel="prefetch" href="/assets/js/163.b59e0d60.js"><link rel="prefetch" href="/assets/js/164.d9eb8228.js"><link rel="prefetch" href="/assets/js/165.ca624c79.js"><link rel="prefetch" href="/assets/js/166.025b2ba1.js"><link rel="prefetch" href="/assets/js/167.abc982cc.js"><link rel="prefetch" href="/assets/js/168.27ca13dc.js"><link rel="prefetch" href="/assets/js/17.43b3c1c8.js"><link rel="prefetch" href="/assets/js/170.626319e1.js"><link rel="prefetch" href="/assets/js/171.a221dddf.js"><link rel="prefetch" href="/assets/js/172.464b2361.js"><link rel="prefetch" href="/assets/js/173.96a3afee.js"><link rel="prefetch" href="/assets/js/174.116607c2.js"><link rel="prefetch" href="/assets/js/175.ea3e8659.js"><link rel="prefetch" href="/assets/js/176.7d7b8afc.js"><link rel="prefetch" href="/assets/js/177.a6e00aa0.js"><link rel="prefetch" href="/assets/js/178.1f93afaf.js"><link rel="prefetch" href="/assets/js/179.3aa00dcd.js"><link rel="prefetch" href="/assets/js/18.d81b44d5.js"><link rel="prefetch" href="/assets/js/180.f8b2b75a.js"><link rel="prefetch" href="/assets/js/181.8e11258a.js"><link rel="prefetch" href="/assets/js/182.22243941.js"><link rel="prefetch" href="/assets/js/183.d051fdf6.js"><link rel="prefetch" href="/assets/js/184.a994075e.js"><link rel="prefetch" href="/assets/js/185.776c7e16.js"><link rel="prefetch" href="/assets/js/186.f1887955.js"><link rel="prefetch" href="/assets/js/187.da0d3626.js"><link rel="prefetch" href="/assets/js/188.8dfc358f.js"><link rel="prefetch" href="/assets/js/189.dcac5a59.js"><link rel="prefetch" href="/assets/js/19.1b3d66e1.js"><link rel="prefetch" href="/assets/js/190.c7e413d0.js"><link rel="prefetch" href="/assets/js/191.d9806121.js"><link rel="prefetch" href="/assets/js/192.869791da.js"><link rel="prefetch" href="/assets/js/193.2d74c4c8.js"><link rel="prefetch" href="/assets/js/194.c73a1909.js"><link rel="prefetch" href="/assets/js/195.e8c74834.js"><link rel="prefetch" href="/assets/js/20.bd5949ec.js"><link rel="prefetch" href="/assets/js/21.3fcf98cf.js"><link rel="prefetch" href="/assets/js/22.2fa1e2e8.js"><link rel="prefetch" href="/assets/js/23.1ae64bb4.js"><link rel="prefetch" href="/assets/js/24.7bdf7387.js"><link rel="prefetch" href="/assets/js/25.392c436e.js"><link rel="prefetch" href="/assets/js/26.58acbd4b.js"><link rel="prefetch" href="/assets/js/27.c725bdd5.js"><link rel="prefetch" href="/assets/js/28.6c9bda1e.js"><link rel="prefetch" href="/assets/js/29.e656b537.js"><link rel="prefetch" href="/assets/js/30.2c326fc7.js"><link rel="prefetch" href="/assets/js/31.e6c9fa30.js"><link rel="prefetch" href="/assets/js/32.c9c88437.js"><link rel="prefetch" href="/assets/js/33.0c53373c.js"><link rel="prefetch" href="/assets/js/34.9821e543.js"><link rel="prefetch" href="/assets/js/35.de8253eb.js"><link rel="prefetch" href="/assets/js/36.d182f929.js"><link rel="prefetch" href="/assets/js/37.9fa79014.js"><link rel="prefetch" href="/assets/js/38.9bebff76.js"><link rel="prefetch" href="/assets/js/39.19a3a2d4.js"><link rel="prefetch" href="/assets/js/4.564edb9d.js"><link rel="prefetch" href="/assets/js/40.cca6955f.js"><link rel="prefetch" href="/assets/js/41.854cd09a.js"><link rel="prefetch" href="/assets/js/42.ca7b612f.js"><link rel="prefetch" href="/assets/js/43.87027d58.js"><link rel="prefetch" href="/assets/js/44.8c2b4f4b.js"><link rel="prefetch" href="/assets/js/45.dffb4e08.js"><link rel="prefetch" href="/assets/js/46.f58049a5.js"><link rel="prefetch" href="/assets/js/47.6854070c.js"><link rel="prefetch" href="/assets/js/48.6cd9fa3d.js"><link rel="prefetch" href="/assets/js/49.e8861afa.js"><link rel="prefetch" href="/assets/js/5.5c31d62f.js"><link rel="prefetch" href="/assets/js/50.703bffab.js"><link rel="prefetch" href="/assets/js/51.6655c373.js"><link rel="prefetch" href="/assets/js/52.deb2eb09.js"><link rel="prefetch" href="/assets/js/53.6e0ed77d.js"><link rel="prefetch" href="/assets/js/54.b05c58ad.js"><link rel="prefetch" href="/assets/js/55.49c8164e.js"><link rel="prefetch" href="/assets/js/56.a5574e6b.js"><link rel="prefetch" href="/assets/js/57.58cb0de4.js"><link rel="prefetch" href="/assets/js/58.52345112.js"><link rel="prefetch" href="/assets/js/59.663ce78d.js"><link rel="prefetch" href="/assets/js/6.a9df34ee.js"><link rel="prefetch" href="/assets/js/60.f06adde2.js"><link rel="prefetch" href="/assets/js/61.170255a1.js"><link rel="prefetch" href="/assets/js/62.9d120050.js"><link rel="prefetch" href="/assets/js/63.70cced6b.js"><link rel="prefetch" href="/assets/js/64.577f3548.js"><link rel="prefetch" href="/assets/js/65.c037b29d.js"><link rel="prefetch" href="/assets/js/66.7dd1045f.js"><link rel="prefetch" href="/assets/js/67.d3aa4d6c.js"><link rel="prefetch" href="/assets/js/68.526dbb61.js"><link rel="prefetch" href="/assets/js/69.58269266.js"><link rel="prefetch" href="/assets/js/7.6609d4d6.js"><link rel="prefetch" href="/assets/js/70.64108f1b.js"><link rel="prefetch" href="/assets/js/71.1e95e0a6.js"><link rel="prefetch" href="/assets/js/72.42e7ec94.js"><link rel="prefetch" href="/assets/js/73.dad4e1c5.js"><link rel="prefetch" href="/assets/js/74.28ea286a.js"><link rel="prefetch" href="/assets/js/75.dd6d4c6f.js"><link rel="prefetch" href="/assets/js/76.ca6539df.js"><link rel="prefetch" href="/assets/js/77.feb13b0e.js"><link rel="prefetch" href="/assets/js/78.321e90e6.js"><link rel="prefetch" href="/assets/js/79.68eb8fcf.js"><link rel="prefetch" href="/assets/js/8.396d51fd.js"><link rel="prefetch" href="/assets/js/80.4edb5321.js"><link rel="prefetch" href="/assets/js/81.735d7e57.js"><link rel="prefetch" href="/assets/js/82.fa120bdf.js"><link rel="prefetch" href="/assets/js/83.bf755f94.js"><link rel="prefetch" href="/assets/js/84.9b32070c.js"><link rel="prefetch" href="/assets/js/85.592aca7c.js"><link rel="prefetch" href="/assets/js/86.4dcd9e73.js"><link rel="prefetch" href="/assets/js/87.a9e546aa.js"><link rel="prefetch" href="/assets/js/88.2a423212.js"><link rel="prefetch" href="/assets/js/89.5f455115.js"><link rel="prefetch" href="/assets/js/9.adb074c6.js"><link rel="prefetch" href="/assets/js/90.5202da0a.js"><link rel="prefetch" href="/assets/js/91.02cee99d.js"><link rel="prefetch" href="/assets/js/92.f16bad0b.js"><link rel="prefetch" href="/assets/js/93.f933634f.js"><link rel="prefetch" href="/assets/js/94.8e7b1d65.js"><link rel="prefetch" href="/assets/js/95.ee0e4a0a.js"><link rel="prefetch" href="/assets/js/96.e21d78c2.js"><link rel="prefetch" href="/assets/js/97.c87e514e.js"><link rel="prefetch" href="/assets/js/98.d123ac92.js"><link rel="prefetch" href="/assets/js/99.92d1b416.js">
    <link rel="stylesheet" href="/assets/css/0.styles.91f57736.css">
  </head>
  <body>
    <div id="app" data-server-rendered="true"><div class="theme-container no-sidebar" data-v-3ba18f14><div data-v-3ba18f14><div id="loader-wrapper" class="loading-wrapper" data-v-041fef5b data-v-3ba18f14 data-v-3ba18f14><div class="loader-main" data-v-041fef5b><div data-v-041fef5b></div><div data-v-041fef5b></div><div data-v-041fef5b></div><div data-v-041fef5b></div></div> <!----> <!----></div> <div class="password-shadow password-wrapper-out" style="display:none;" data-v-68139a52 data-v-3ba18f14 data-v-3ba18f14><h3 class="title" style="display:none;" data-v-68139a52 data-v-68139a52>JavaKeeper</h3> <!----> <label id="box" class="inputBox" style="display:none;" data-v-68139a52 data-v-68139a52><input type="password" value="" data-v-68139a52> <span data-v-68139a52>Konck! Knock!</span> <button data-v-68139a52>OK</button></label> <div class="footer" style="display:none;" data-v-68139a52 data-v-68139a52><span data-v-68139a52><i class="iconfont reco-theme" data-v-68139a52></i> <a target="blank" href="https://vuepress-theme-reco.recoluan.com" data-v-68139a52>vuePress-theme-reco</a></span> <span data-v-68139a52><i class="iconfont reco-copyright" data-v-68139a52></i> <a data-v-68139a52><span data-v-68139a52>海星</span>
            
          <!---->
          2020
        </a></span></div></div> <div class="hide" data-v-3ba18f14><header class="navbar" data-v-3ba18f14><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/" class="home-link router-link-active"><!----> <span class="site-name">JavaKeeper</span></a> <div class="links"><div class="color-picker"><a class="color-button"><i class="iconfont reco-color"></i></a> <div class="color-picker-menu" style="display:none;"><div class="mode-options"><h4 class="title">Choose mode</h4> <ul class="color-mode-options"><li class="dark">dark</li><li class="auto active">auto</li><li class="light">light</li></ul></div></div></div> <div class="search-box"><i class="iconfont reco-search"></i> <input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/java/" class="nav-link"><i class="iconfont undefined"></i>
  Java
</a></div><div class="nav-item"><a href="/data-structure-algorithms/" class="nav-link"><i class="iconfont undefined"></i>
  数据结构与算法
</a></div><div class="nav-item"><a href="/data-store/" class="nav-link"><i class="iconfont undefined"></i>
  数据存储与缓存
</a></div><div class="nav-item"><a href="/interview/" class="nav-link"><i class="iconfont undefined"></i>
  直击面试
</a></div> <a href="https://github.com/Jstarfish/JavaKeeper" target="_blank" rel="noopener noreferrer" class="repo-link"><i class="iconfont reco-github"></i>
    GitHub
    <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></nav></div></header> <div class="sidebar-mask" data-v-3ba18f14></div> <aside class="sidebar" data-v-3ba18f14><div class="personal-info-wrapper" data-v-5f6acefd data-v-3ba18f14><!----> <h3 class="name" data-v-5f6acefd>
    海星
  </h3> <div class="num" data-v-5f6acefd><div data-v-5f6acefd><h3 data-v-5f6acefd>0</h3> <h6 data-v-5f6acefd>Article</h6></div> <div data-v-5f6acefd><h3 data-v-5f6acefd>0</h3> <h6 data-v-5f6acefd>Tag</h6></div></div> <hr data-v-5f6acefd></div> <nav class="nav-links"><div class="nav-item"><a href="/java/" class="nav-link"><i class="iconfont undefined"></i>
  Java
</a></div><div class="nav-item"><a href="/data-structure-algorithms/" class="nav-link"><i class="iconfont undefined"></i>
  数据结构与算法
</a></div><div class="nav-item"><a href="/data-store/" class="nav-link"><i class="iconfont undefined"></i>
  数据存储与缓存
</a></div><div class="nav-item"><a href="/interview/" class="nav-link"><i class="iconfont undefined"></i>
  直击面试
</a></div> <a href="https://github.com/Jstarfish/JavaKeeper" target="_blank" rel="noopener noreferrer" class="repo-link"><i class="iconfont reco-github"></i>
    GitHub
    <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></nav> <!----> </aside> <div class="password-shadow password-wrapper-in" style="display:none;" data-v-68139a52 data-v-3ba18f14><h3 class="title" style="display:none;" data-v-68139a52 data-v-68139a52></h3> <!----> <label id="box" class="inputBox" style="display:none;" data-v-68139a52 data-v-68139a52><input type="password" value="" data-v-68139a52> <span data-v-68139a52>Konck! Knock!</span> <button data-v-68139a52>OK</button></label> <div class="footer" style="display:none;" data-v-68139a52 data-v-68139a52><span data-v-68139a52><i class="iconfont reco-theme" data-v-68139a52></i> <a target="blank" href="https://vuepress-theme-reco.recoluan.com" data-v-68139a52>vuePress-theme-reco</a></span> <span data-v-68139a52><i class="iconfont reco-copyright" data-v-68139a52></i> <a data-v-68139a52><span data-v-68139a52>海星</span>
            
          <!---->
          2020
        </a></span></div></div> <div data-v-3ba18f14><main class="page"><div class="page-title" style="display:none;"><h1 class="title"></h1> <div data-v-5d8dbdb4><i class="iconfont reco-account" data-v-5d8dbdb4><span data-v-5d8dbdb4>海星</span></i> <!----> <!----> <!----></div></div> <div class="theme-reco-content content__default" style="display:none;"><p>Redis 作为内存数据库，拥有非常高的性能，单个实例的QPS能够达到10W左右。但我们在使用Redis时，经常时不时会出现访问延迟很大的情况，如果你不知道Redis的内部实现原理，在排查问题时就会一头雾水。</p> <p>很多时候，Redis出现访问延迟变大，都与我们的使用不当或运维不合理导致的。</p> <p>这篇文章我们就来分析一下Redis在使用过程中，经常会遇到的延迟问题以及如何定位和分析。</p> <h2 id="使用复杂度高的命令"><a href="#使用复杂度高的命令" class="header-anchor">#</a> 使用复杂度高的命令</h2> <p>如果在使用Redis时，发现访问延迟突然增大，如何进行排查？</p> <p>首先，第一步，建议你去查看一下Redis的慢日志。Redis提供了慢日志命令的统计功能，我们通过以下设置，就可以查看有哪些命令在执行时延迟比较大。</p> <p>首先设置Redis的慢日志阈值，只有超过阈值的命令才会被记录，这里的单位是微妙，例如设置慢日志的阈值为5毫秒，同时设置只保留最近1000条慢日志记录：</p> <div class="language- extra-class"><pre class="language-text"><code># 命令执行超过5毫秒记录慢日志
CONFIG SET slowlog-log-slower-than 5000
# 只保留最近1000条慢日志
CONFIG SET slowlog-max-len 1000
</code></pre></div><p>设置完成之后，所有执行的命令如果延迟大于5毫秒，都会被Redis记录下来，我们执行<code>SLOWLOG get 5</code>查询最近5条慢日志：</p> <div class="language- extra-class"><pre class="language-text"><code>127.0.0.1:6379&gt; SLOWLOG get 5
1) 1) (integer) 32693       # 慢日志ID
   2) (integer) 1593763337  # 执行时间
   3) (integer) 5299        # 执行耗时(微妙)
   4) 1) &quot;LRANGE&quot;           # 具体执行的命令和参数
      2) &quot;user_list_2000&quot;
      3) &quot;0&quot;
      4) &quot;-1&quot;
2) 1) (integer) 32692
   2) (integer) 1593763337
   3) (integer) 5044
   4) 1) &quot;GET&quot;
      2) &quot;book_price_1000&quot;
...
</code></pre></div><p>通过查看慢日志记录，我们就可以知道在什么时间执行哪些命令比较耗时，如果你的业务<strong>经常使用<code>O(n)</code>以上复杂度的命令</strong>，例如<code>sort</code>、<code>sunion</code>、<code>zunionstore</code>，或者在执行<code>O(n)</code>命令时操作的数据量比较大，这些情况下Redis处理数据时就会很耗时。</p> <p>如果你的服务请求量并不大，但Redis实例的CPU使用率很高，很有可能是使用了复杂度高的命令导致的。</p> <p>解决方案就是，不使用这些复杂度较高的命令，并且一次不要获取太多的数据，每次尽量操作少量的数据，让Redis可以及时处理返回。</p> <h2 id="存储大key"><a href="#存储大key" class="header-anchor">#</a> 存储大key</h2> <p>如果查询慢日志发现，并不是复杂度较高的命令导致的，例如都是<code>SET</code>、<code>DELETE</code>操作出现在慢日志记录中，那么你就要怀疑是否存在Redis写入了大key的情况。</p> <p>Redis在写入数据时，需要为新的数据分配内存，当从Redis中删除数据时，它会释放对应的内存空间。</p> <p>如果一个key写入的数据非常大，Redis在<strong>分配内存时也会比较耗时</strong>。同样的，当删除这个key的数据时，<strong>释放内存也会耗时比较久</strong>。</p> <p>你需要检查你的业务代码，是否存在写入大key的情况，需要评估写入数据量的大小，业务层应该避免一个key存入过大的数据量。</p> <p>那么有没有什么办法可以扫描现在Redis中是否存在大key的数据吗？</p> <p>Redis也提供了扫描大key的方法：</p> <div class="language- extra-class"><pre class="language-text"><code>redis-cli -h $host -p $port --bigkeys -i 0.01
</code></pre></div><p>使用上面的命令就可以扫描出整个实例key大小的分布情况，它是以类型维度来展示的。</p> <p>需要注意的是当我们在线上实例进行大key扫描时，Redis的QPS会突增，为了降低扫描过程中对Redis的影响，我们需要控制扫描的频率，使用<code>-i</code>参数控制即可，它表示扫描过程中每次扫描的时间间隔，单位是秒。</p> <p>使用这个命令的原理，其实就是Redis在内部执行<code>scan</code>命令，遍历所有key，然后针对不同类型的key执行<code>strlen</code>、<code>llen</code>、<code>hlen</code>、<code>scard</code>、<code>zcard</code>来获取字符串的长度以及容器类型(list/dict/set/zset)的元素个数。</p> <p>而对于容器类型的key，只能扫描出元素最多的key，但元素最多的key不一定占用内存最多，这一点需要我们注意下。不过使用这个命令一般我们是可以对整个实例中key的分布情况有比较清晰的了解。</p> <p>针对大key的问题，Redis官方在4.0版本推出了<code>lazy-free</code>的机制，用于异步释放大key的内存，降低对Redis性能的影响。即使这样，我们也不建议使用大key，大key在集群的迁移过程中，也会影响到迁移的性能，这个后面在介绍集群相关的文章时，会再详细介绍到。</p> <h2 id="集中过期"><a href="#集中过期" class="header-anchor">#</a> 集中过期</h2> <p>有时你会发现，平时在使用Redis时没有延时比较大的情况，但在某个时间点突然出现一波延时，而且<strong>报慢的时间点很有规律，例如某个整点，或者间隔多久就会发生一次</strong>。</p> <p>如果出现这种情况，就需要考虑是否存在大量key集中过期的情况。</p> <p>如果有大量的key在某个固定时间点集中过期，在这个时间点访问Redis时，就有可能导致延迟增加。</p> <p>Redis的过期策略采用主动过期+懒惰过期两种策略：</p> <ul><li>主动过期：Redis内部维护一个定时任务，默认每隔100毫秒会从过期字典中随机取出20个key，删除过期的key，如果过期key的比例超过了25%，则继续获取20个key，删除过期的key，循环往复，直到过期key的比例下降到25%或者这次任务的执行耗时超过了25毫秒，才会退出循环</li> <li>懒惰过期：只有当访问某个key时，才判断这个key是否已过期，如果已经过期，则从实例中删除</li></ul> <p>注意，<strong>Redis的主动过期的定时任务，也是在Redis主线程中执行的</strong>，也就是说如果在执行主动过期的过程中，出现了需要大量删除过期key的情况，那么在业务访问时，必须等这个过期任务执行结束，才可以处理业务请求。此时就会出现，业务访问延时增大的问题，最大延迟为25毫秒。</p> <p>而且这个访问延迟的情况，<strong>不会记录在慢日志里</strong>。慢日志中<strong>只记录真正执行某个命令的耗时</strong>，Redis主动过期策略执行在操作命令之前，如果操作命令耗时达不到慢日志阈值，它是不会计算在慢日志统计中的，但我们的业务却感到了延迟增大。</p> <p>此时你需要检查你的业务，是否真的存在集中过期的代码，一般集中过期使用的命令是<code>expireat</code>或<code>pexpireat</code>命令，在代码中搜索这个关键字就可以了。</p> <p>如果你的业务确实需要集中过期掉某些key，又不想导致Redis发生抖动，有什么优化方案？</p> <p>解决方案是，<strong>在集中过期时增加一个随机时间，把这些需要过期的key的时间打散即可。</strong></p> <p>伪代码可以这么写：</p> <div class="language- extra-class"><pre class="language-text"><code># 在过期时间点之后的5分钟内随机过期掉
redis.expireat(key, expire_time + random(300))
</code></pre></div><p>这样Redis在处理过期时，不会因为集中删除key导致压力过大，阻塞主线程。</p> <p>另外，除了业务使用需要注意此问题之外，还可以通过运维手段来及时发现这种情况。</p> <p>做法是我们需要把Redis的各项运行数据监控起来，执行<code>info</code>可以拿到所有的运行数据，在这里我们需要重点关注<code>expired_keys</code>这一项，它代表整个实例到目前为止，累计删除过期key的数量。</p> <p>我们需要对这个指标监控，当在<strong>很短时间内这个指标出现突增</strong>时，需要及时报警出来，然后与业务报慢的时间点对比分析，确认时间是否一致，如果一致，则可以认为确实是因为这个原因导致的延迟增大。</p> <h2 id="实例内存达到上限"><a href="#实例内存达到上限" class="header-anchor">#</a> 实例内存达到上限</h2> <p>有时我们把Redis当做纯缓存使用，就会给实例设置一个内存上限<code>maxmemory</code>，然后开启LRU淘汰策略。</p> <p>当实例的内存达到了<code>maxmemory</code>后，你会发现之后的每次写入新的数据，有可能变慢了。</p> <p>导致变慢的原因是，当Redis内存达到<code>maxmemory</code>后，每次写入新的数据之前，必须先踢出一部分数据，让内存维持在<code>maxmemory</code>之下。</p> <p>这个踢出旧数据的逻辑也是需要消耗时间的，而具体耗时的长短，要取决于配置的淘汰策略：</p> <ul><li>allkeys-lru：不管key是否设置了过期，淘汰最近最少访问的key</li> <li>volatile-lru：只淘汰最近最少访问并设置过期的key</li> <li>allkeys-random：不管key是否设置了过期，随机淘汰</li> <li>volatile-random：只随机淘汰有设置过期的key</li> <li>allkeys-ttl：不管key是否设置了过期，淘汰即将过期的key</li> <li>noeviction：不淘汰任何key，满容后再写入直接报错</li> <li>allkeys-lfu：不管key是否设置了过期，淘汰访问频率最低的key（4.0+支持）</li> <li>volatile-lfu：只淘汰访问频率最低的过期key（4.0+支持）</li></ul> <p>具体使用哪种策略，需要根据业务场景来决定。</p> <p>我们最常使用的一般是<code>allkeys-lru</code>或<code>volatile-lru</code>策略，它们的处理逻辑是，每次从实例中随机取出一批key（可配置），然后淘汰一个最少访问的key，之后把剩下的key暂存到一个池子中，继续随机取出一批key，并与之前池子中的key比较，再淘汰一个最少访问的key。以此循环，直到内存降到<code>maxmemory</code>之下。</p> <p>如果使用的是<code>allkeys-random</code>或<code>volatile-random</code>策略，那么就会快很多，因为是随机淘汰，那么就少了比较key访问频率时间的消耗了，随机拿出一批key后直接淘汰即可，因此这个策略要比上面的LRU策略执行快一些。</p> <p>但以上这些逻辑都是在访问Redis时，<strong>真正命令执行之前执行的</strong>，也就是它会影响我们访问Redis时执行的命令。</p> <p>另外，如果此时Redis实例中有存储大key，那么<strong>在淘汰大key释放内存时，这个耗时会更加久，延迟更大</strong>，这需要我们格外注意。</p> <p>如果你的业务访问量非常大，并且必须设置<code>maxmemory</code>限制实例的内存上限，同时面临淘汰key导致延迟增大的的情况，要想缓解这种情况，除了上面说的避免存储大key、使用随机淘汰策略之外，也可以考虑<strong>拆分实例</strong>的方法来缓解，拆分实例可以把一个实例淘汰key的压力<strong>分摊到多个实例</strong>上，可以在一定程度降低延迟。</p> <h2 id="fork耗时严重"><a href="#fork耗时严重" class="header-anchor">#</a> fork耗时严重</h2> <p>如果你的Redis开启了自动生成RDB和AOF重写功能，那么有可能在后台生成RDB和AOF重写时导致Redis的访问延迟增大，而等这些任务执行完毕后，延迟情况消失。</p> <p>遇到这种情况，一般就是执行生成RDB和AOF重写任务导致的。</p> <p>生成RDB和AOF都需要父进程<code>fork</code>出一个子进程进行数据的持久化，<strong>在<code>fork</code>执行过程中，父进程需要拷贝内存页表给子进程，如果整个实例内存占用很大，那么需要拷贝的内存页表会比较耗时，此过程会消耗大量的CPU资源，在完成<code>fork</code>之前，整个实例会被阻塞住，无法处理任何请求，如果此时CPU资源紧张，那么<code>fork</code>的时间会更长，甚至达到秒级。这会严重影响Redis的性能</strong>。</p> <p>具体原理也可以参考我之前写的文章：<a href="http://kaito-kidd.com/2020/06/29/redis-persistence-rdb-aof/" target="_blank" rel="noopener noreferrer">Redis持久化是如何做的？RDB和AOF对比分析<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a>。</p> <p>我们可以执行<code>info</code>命令，查看最后一次<code>fork</code>执行的耗时<code>latest_fork_usec</code>，单位微妙。这个时间就是整个实例阻塞无法处理请求的时间。</p> <p>除了因为备份的原因生成RDB之外，<strong>在主从节点第一次建立数据同步时</strong>，主节点也会生成RDB文件给从节点进行一次全量同步，这时也会对Redis产生性能影响。</p> <p>要想避免这种情况，我们需要规划好数据备份的周期，建议在<strong>从节点上执行备份，而且最好放在低峰期执行</strong>。如果对于丢失数据不敏感的业务，那么不建议开启AOF和AOF重写功能。</p> <p>另外，<code>fork</code>的耗时也与系统有关，如果把Redis部署在虚拟机上，那么这个时间也会增大。所以使用Redis时建议部署在物理机上，降低<code>fork</code>的影响。</p> <h2 id="绑定cpu"><a href="#绑定cpu" class="header-anchor">#</a> 绑定CPU</h2> <p>很多时候，我们在部署服务时，为了提高性能，降低程序在使用多个CPU时上下文切换的性能损耗，一般会采用进程绑定CPU的操作。</p> <p>但在使用Redis时，我们不建议这么干，原因如下。</p> <p><strong>绑定CPU的Redis，在进行数据持久化时，<code>fork</code>出的子进程，子进程会继承父进程的CPU使用偏好，而此时子进程会消耗大量的CPU资源进行数据持久化，子进程会与主进程发生CPU争抢，这也会导致主进程的CPU资源不足访问延迟增大。</strong></p> <p>所以在部署Redis进程时，如果需要开启RDB和AOF重写机制，一定不能进行CPU绑定操作！</p> <h2 id="开启aof"><a href="#开启aof" class="header-anchor">#</a> 开启AOF</h2> <p>上面提到了，当执行AOF文件重写时会因为<code>fork</code>执行耗时导致Redis延迟增大，除了这个之外，如果开启AOF机制，设置的策略不合理，也会导致性能问题。</p> <p>开启AOF后，Redis会把写入的命令实时写入到文件中，但写入文件的过程是先写入内存，等内存中的数据超过一定阈值或达到一定时间后，内存中的内容才会被真正写入到磁盘中。</p> <p>AOF为了保证文件写入磁盘的安全性，提供了3种刷盘机制：</p> <ul><li><code>appendfsync always</code>：每次写入都刷盘，对性能影响最大，占用磁盘IO比较高，数据安全性最高</li> <li><code>appendfsync everysec</code>：1秒刷一次盘，对性能影响相对较小，节点宕机时最多丢失1秒的数据</li> <li><code>appendfsync no</code>：按照操作系统的机制刷盘，对性能影响最小，数据安全性低，节点宕机丢失数据取决于操作系统刷盘机制</li></ul> <p>当使用第一种机制<code>appendfsync always</code>时，Redis每处理一次写命令，都会把这个命令写入磁盘，而且<strong>这个操作是在主线程中执行的</strong>。</p> <p>内存中的的数据写入磁盘，这个会加重磁盘的IO负担，操作磁盘成本要比操作内存的代价大得多。如果写入量很大，那么每次更新都会写入磁盘，此时机器的磁盘IO就会非常高，拖慢Redis的性能，因此我们不建议使用这种机制。</p> <p>与第一种机制对比，<code>appendfsync everysec</code>会每隔1秒刷盘，而<code>appendfsync no</code>取决于操作系统的刷盘时间，安全性不高。因此我们推荐使用<code>appendfsync everysec</code>这种方式，在最坏的情况下，只会丢失1秒的数据，但它能保持较好的访问性能。</p> <p>当然，对于有些业务场景，对丢失数据并不敏感，也可以不开启AOF。</p> <h2 id="使用swap"><a href="#使用swap" class="header-anchor">#</a> 使用Swap</h2> <p>如果你发现Redis突然变得非常慢，<strong>每次访问的耗时都达到了几百毫秒甚至秒级</strong>，那此时就检查Redis是否使用到了Swap，这种情况下Redis基本上已经无法提供高性能的服务。</p> <p>我们知道，操作系统提供了Swap机制，目的是为了当内存不足时，可以把一部分内存中的数据换到磁盘上，以达到对内存使用的缓冲。</p> <p>但当内存中的数据被换到磁盘上后，访问这些数据就需要从磁盘中读取，这个速度要比内存慢太多！</p> <p><strong>尤其是针对Redis这种高性能的内存数据库来说，如果Redis中的内存被换到磁盘上，对于Redis这种性能极其敏感的数据库，这个操作时间是无法接受的。</strong></p> <p>我们需要检查机器的内存使用情况，确认是否确实是因为内存不足导致使用到了Swap。</p> <p>如果确实使用到了Swap，要及时整理内存空间，释放出足够的内存供Redis使用，然后释放Redis的Swap，让Redis重新使用内存。</p> <p>释放Redis的Swap过程通常要重启实例，为了避免重启实例对业务的影响，一般先进行主从切换，然后释放旧主节点的Swap，重新启动服务，待数据同步完成后，再切换回主节点即可。</p> <p>可见，当Redis使用到Swap后，此时的Redis的高性能基本被废掉，所以我们需要提前预防这种情况。</p> <p><strong>我们需要对Redis机器的内存和Swap使用情况进行监控，在内存不足和使用到Swap时及时报警出来，及时进行相应的处理。</strong></p> <h2 id="网卡负载过高"><a href="#网卡负载过高" class="header-anchor">#</a> 网卡负载过高</h2> <p>如果以上产生性能问题的场景，你都规避掉了，而且Redis也稳定运行了很长时间，但在某个时间点之后开始，访问Redis开始变慢了，而且一直持续到现在，这种情况是什么原因导致的？</p> <p>之前我们就遇到这种问题，<strong>特点就是从某个时间点之后就开始变慢，并且一直持续</strong>。这时你需要检查一下机器的网卡流量，是否存在网卡流量被跑满的情况。</p> <p><strong>网卡负载过高，在网络层和TCP层就会出现数据发送延迟、数据丢包等情况。Redis的高性能除了内存之外，就在于网络IO，请求量突增会导致网卡负载变高。</strong></p> <p>如果出现这种情况，你需要排查这个机器上的哪个Redis实例的流量过大占满了网络带宽，然后确认流量突增是否属于业务正常情况，如果属于那就需要及时扩容或迁移实例，避免这个机器的其他实例受到影响。</p> <p>运维层面，我们需要对机器的各项指标增加监控，包括网络流量，在达到阈值时提前报警，及时与业务确认并扩容。</p> <h2 id="总结"><a href="#总结" class="header-anchor">#</a> 总结</h2> <p>以上我们总结了Redis中常见的可能导致延迟增大甚至阻塞的场景，这其中既涉及到了业务的使用问题，也涉及到Redis的运维问题。</p> <p>可见，要想保证Redis高性能的运行，其中涉及到CPU、内存、网络，甚至磁盘的方方面面，其中还包括操作系统的相关特性的使用。</p> <p>作为开发人员，我们需要了解Redis的运行机制，例如各个命令的执行时间复杂度、数据过期策略、数据淘汰策略等，使用合理的命令，并结合业务场景进行优化。</p> <p>作为DBA运维人员，需要了解数据持久化、操作系统<code>fork</code>原理、Swap机制等，并对Redis的容量进行合理规划，预留足够的机器资源，对机器做好完善的监控，才能保证Redis的稳定运行。</p></div> <footer class="page-edit" style="display:none;"><!----> <!----></footer> <!----> <!----> <!----></main> <!----></div></div></div></div><div class="global-ui"><div class="back-to-ceiling" style="right:1rem;bottom:6rem;width:2.5rem;height:2.5rem;border-radius:.25rem;line-height:2.5rem;display:none;" data-v-db14854a data-v-db14854a><svg t="1574745035067" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5404" class="icon" data-v-db14854a><path d="M526.60727968 10.90185116a27.675 27.675 0 0 0-29.21455937 0c-131.36607665 82.28402758-218.69155461 228.01873535-218.69155402 394.07834331a462.20625001 462.20625001 0 0 0 5.36959153 69.94390903c1.00431239 6.55289093-0.34802892 13.13561351-3.76865779 18.80351572-32.63518765 54.11355614-51.75690182 118.55860487-51.7569018 187.94566865a371.06718723 371.06718723 0 0 0 11.50484808 91.98906777c6.53300375 25.50556257 41.68394495 28.14064038 52.69160883 4.22606766 17.37162448-37.73630017 42.14135425-72.50938081 72.80769204-103.21549295 2.18761121 3.04276886 4.15646224 6.24463696 6.40373557 9.22774369a1871.4375 1871.4375 0 0 0 140.04691725 5.34970492 1866.36093723 1866.36093723 0 0 0 140.04691723-5.34970492c2.24727335-2.98310674 4.21612437-6.18497483 6.3937923-9.2178004 30.66633723 30.70611158 55.4360664 65.4791928 72.80769147 103.21549355 11.00766384 23.91457269 46.15860503 21.27949489 52.69160879-4.22606768a371.15156223 371.15156223 0 0 0 11.514792-91.99901164c0-69.36717486-19.13165746-133.82216804-51.75690182-187.92578088-3.42062944-5.66790279-4.76302748-12.26056868-3.76865837-18.80351632a462.20625001 462.20625001 0 0 0 5.36959269-69.943909c-0.00994388-166.08943902-87.32547796-311.81420293-218.6915546-394.09823051zM605.93803103 357.87693858a93.93749974 93.93749974 0 1 1-187.89594924 6.1e-7 93.93749974 93.93749974 0 0 1 187.89594924-6.1e-7z" p-id="5405" data-v-db14854a></path><path d="M429.50777625 765.63860547C429.50777625 803.39355007 466.44236686 1000.39046097 512.00932183 1000.39046097c45.56695499 0 82.4922232-197.00623328 82.5015456-234.7518555 0-37.75494459-36.9345906-68.35043303-82.4922232-68.34111062-45.57627738-0.00932239-82.52019037 30.59548842-82.51086798 68.34111062z" p-id="5406" data-v-db14854a></path></svg></div><!----></div></div>
    <script src="/assets/js/app.447d4224.js" defer></script><script src="/assets/js/3.9d76740c.js" defer></script><script src="/assets/js/1.c4fd7d2e.js" defer></script><script src="/assets/js/169.41e753a2.js" defer></script>
  </body>
</html>
